package handler

import (
	"encoding/json"
	mqtt "github.com/eclipse/paho.mqtt.golang"
	"github.com/gorilla/websocket"
	"github.com/sirupsen/logrus"
	"log"
	"net/http"
	"sync"
	"time"
	"wlrIms/mqttserver"
)

// Client 结构体用于存储客户端的连接信息
type Client struct {
	conn *websocket.Conn
}

var (
	upgrader = websocket.Upgrader{
		ReadBufferSize:  1024,
		WriteBufferSize: 1024,
		CheckOrigin: func(r *http.Request) bool {
			// 在这里检查请求的来源是否合法，返回 true 表示允许升级连接，返回 false 表示拒绝升级连接
			return true // 这里简单地允许所有来源
		},
	}
	clients            = make(map[*websocket.Conn]*Client)
	clientsMutex       sync.Mutex
	WsTopicConnections = make(map[*websocket.Conn]string)
	mu                 sync.Mutex
)

func (pv *webSocketHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	conn, err := upgrader.Upgrade(w, r, nil)
	if err != nil {
		log.Println("WebSocket Upgrade 失败:", err)
		return
	}
	// 创建一个客户端对象，并将其存储到 cli  nts map 中
	client := &Client{conn: conn}
	clientsMutex.Lock()
	clients[conn] = client
	clientsMutex.Unlock()

	// 接收客户端消息
	go pv.receiveMessages(conn)
	// 在连接成功后，可以进行一些初始化操作
}

func (pv *webSocketHandler) receiveMessages(conn *websocket.Conn) {
	defer func() {
		// 在函数退出时，删除 clients map 中的客户端连接信息
		clientsMutex.Lock()
		delete(clients, conn)
		clientsMutex.Unlock()
		conn.Close()
	}()

	for {
		// 读取客户端发送的消息
		messageType, message, err := conn.ReadMessage()
		if err != nil {
			if websocket.IsCloseError(err, websocket.CloseNormalClosure, websocket.CloseGoingAway) {
				logrus.Println("客户端关闭连接:", err)
				break
			}
			//删除对应的con连接
			logrus.Println("接收消息失败: ", err)
			for _, value := range WsTopicConnections {
				//打印对应的值
				logrus.Println("value", value)
			}
			delete(WsTopicConnections, conn)
			break
		}
		infos := ReqNavigation{}
		if err := json.Unmarshal([]byte(string(message)), &infos); err != nil {
		} else {
			logrus.Info("robotSn:  ", string(infos.RobotSn))
			logrus.Info(" navigation:", string(infos.Navigation))
			publishTopic := "Navigation" + string(infos.RobotSn)
			mu.Lock()
			WsTopicConnections[conn] = infos.RobotSn
			mu.Unlock()
			var replyMessage string
			mqttserver.PublishMessage(mqttclient, publishTopic, string(infos.Navigation))
			messageChan := make(chan mqtt.Message)
			mqttserver.PerformSub(mqttclient, infos.RobotSn, messageChan)

			var result Response
			for {
				select {
				case msg := <-messageChan:
					data := mqttserver.ProcessMsg(mqttclient, msg)
					err := json.Unmarshal([]byte(data), &result)
					if err != nil {
						logrus.Println("JSON decoding error:", err)
						return
					} else {
						replyMessage = data
						//订阅的主题
					}
				case <-time.After(10 * time.Minute): // 设置超时时间为5秒
					//超时30min后，设置取消订阅
					logrus.Info("订阅MQTT超时 ", result.RobotSn)
					mqttserver.CancelSub(mqttclient, result.RobotSn, messageChan)
					//1.删除topic 取消订阅
					//2.删除map
					if err = conn.WriteMessage(messageType, []byte(replyMessage)); err != nil {
						log.Println("回复消息失败:", err)
						break
					}
					break
				}
				//判断map中是否含有元素
				if len(WsTopicConnections) == 0 {
					break
				}
				connclients := findValueByKey(WsTopicConnections, result.RobotSn)
				for _, connClient := range connclients {
					if err = connClient.WriteMessage(messageType, []byte(replyMessage)); err != nil {
						log.Println("回复消息失败:", err)
						found := false
						mu.Lock()
						delete(WsTopicConnections, connClient) //判断
						for key, value := range WsTopicConnections {
							if value == result.RobotSn {
								logrus.Printf("Found key '%v' for value '%v'\n", key, value)
								found = true
							}
						}
						if !found {
							logrus.Info("取消订阅的", result.RobotSn)
							mqttserver.CancelSub(mqttclient, result.RobotSn, messageChan)

						}
						mu.Unlock()
					}
				}

			}
			close(messageChan) // 关闭消息通道
		}
	}
}

func findValueByKey(m map[*websocket.Conn]string, value string) []*websocket.Conn {
	var keys []*websocket.Conn
	for k, v := range m {
		if v == value {
			keys = append(keys, k)
		}
	}
	return keys
}
